﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using TFSBugTracking.Properties;

namespace TFSBugTracking
{
    ///<summary>
    /// extension method fot string encryption
    ///</summary>
    public static class StringEncryptionExtionsions
    {
        /// <summary>
        /// Encryptes a string using the supplied key. Encoding is done using RSA encryption.
        /// </summary>
        /// <param name="stringToEncrypt">String that must be encrypted.</param>
        /// <param name="key">Encryptionkey.</param>
        /// <returns>A string representing a byte array separated by a minus sign.</returns>
        /// <exception cref="ArgumentException">Occurs when stringToEncrypt or key is null or empty.</exception>
        public static string Encrypt(this string stringToEncrypt, string key)
        {
            if (string.IsNullOrEmpty(stringToEncrypt))
                throw new ArgumentException(Resources.StringEncryptionExtionsions_Decrypt_An_empty_string_value_cannot_be_encrypted_);
            

            if (string.IsNullOrEmpty(key))
                throw new ArgumentException(Resources.StringEncryptionExtionsions_Encrypt_Cannot_encrypt_using_an_empty_key__Please_supply_an_encryption_key_);
            
            CspParameters cspp = new CspParameters {Flags = CspProviderFlags.UseMachineKeyStore, KeyContainerName = key};

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspp) {PersistKeyInCsp = true};

            byte[] bytes = rsa.Encrypt(Encoding.UTF8.GetBytes(stringToEncrypt), true);

            return BitConverter.ToString(bytes);
        }

        /// <summary>
        /// Decryptes a string using the supplied key. Decoding is done using RSA encryption.
        /// </summary>
        /// <param name="stringToDecrypt">String that must be decrypted.</param>
        /// <param name="key">Decryptionkey.</param>
        /// <returns>The decrypted string or null if decryption failed.</returns>
        /// <exception cref="ArgumentException">Occurs when stringToDecrypt or key is null or empty.</exception>
        public static string Decrypt(this string stringToDecrypt, string key)
        {
            string result = null;

            if (string.IsNullOrEmpty(stringToDecrypt))
                throw new ArgumentException(Resources.StringEncryptionExtionsions_Decrypt_An_empty_string_value_cannot_be_encrypted_);
            
            if (string.IsNullOrEmpty(key))
                throw new ArgumentException(Resources.StringEncryptionExtionsions_Decrypt_Cannot_decrypt_using_an_empty_key__Please_supply_a_decryption_key_);
            
            try
            {
                CspParameters cspp = new CspParameters { Flags = CspProviderFlags.UseMachineKeyStore, KeyContainerName = key };

                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspp) {PersistKeyInCsp = true};

                string[] decryptArray = stringToDecrypt.Split(new string[] { "-" }, StringSplitOptions.None);
                byte[] decryptByteArray = Array.ConvertAll<string, byte>(decryptArray, (s => Convert.ToByte(byte.Parse(s, System.Globalization.NumberStyles.HexNumber))));


                byte[] bytes = rsa.Decrypt(decryptByteArray, true);

                result = System.Text.UTF8Encoding.UTF8.GetString(bytes);

            }
            finally
            {
                // no need for further processing
            }

            return result;
        }


    }
}
